#include <windows.h>
#include <stdio.h>
#include <mmsystem.h>
#include <math.h>
#include <stdarg.h>						
#include <gl/gl.h>
#include <gl/glu.h>

#include "defines.h"
#include "appManager.h"
#include "glWindow.h"
#include "BezierCurve.h"
#include "JPVec2.h"
#include "JPVec3.h"

appManager *manager;

HWND CreateOurWindow(LPSTR strWindowName,
	int width, int height,
	DWORD dwStyle, bool bFullScreen,
	HINSTANCE hInstance);

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);

void Cleanup(HINSTANCE hInstance);

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
	PSTR szCmdLine, int nCmdShow)			
{	
	HWND		hwnd;
	MSG     msg;	

	manager =  new appManager;

	//initialise and create window
	hwnd = CreateOurWindow("Bouncing Balls", S_WIDTH, S_HEIGHT, 0, false, hInstance);	
	if(hwnd == NULL) return true;

	//initialise opengl and other settings
	manager->init(hwnd);
	
	while (true)					
	{							
		if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
		{
			if (msg.message==WM_QUIT)
				break;
			TranslateMessage (&msg);							
			DispatchMessage (&msg);
		}
		else
		{		
			manager->update(FPS, hwnd);
		}
	}
	Cleanup(hInstance);
	return (int)msg.wParam ;										
}

LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)											
	{														
	case WM_SIZE:
		//resize the open gl window when the window is resized
		manager->getGlWindow()->ResizeGLWindow(LOWORD(lParam),HIWORD(lParam));
		break;	

	case WM_KEYDOWN:    
		manager->getInput()->keyPress(wParam);    
		break;

	case WM_KEYUP:
		manager->getInput()->keyUp(wParam);
		break;

	case WM_RBUTTONDOWN:
		manager->getInput()->keyPress(VK_RBUTTON);
		break;

	case WM_RBUTTONUP:
		manager->getInput()->keyUp(VK_RBUTTON);
		break;

	case WM_LBUTTONDOWN:
		manager->getInput()->keyPress(VK_LBUTTON);
		break;

	case WM_LBUTTONUP:
		manager->getInput()->keyUp(VK_LBUTTON);        
		break;

	case WM_MBUTTONDOWN:
		manager->getInput()->keyPress(VK_MBUTTON);
		break;		

	case WM_MBUTTONUP:
		manager->getInput()->keyUp(VK_MBUTTON);
		break;

		//case WM_MOUSEMOVE:
		//    manager->getInput()->keyPress(wParam);
		//    break;

	case WM_DESTROY:			
		PostQuitMessage(0);	

		break;				
	}
	return DefWindowProc (hwnd, message, wParam, lParam);														
}

HWND CreateOurWindow(LPSTR strWindowName,
	int width, int height,
	DWORD dwStyle, bool bFullScreen,
	HINSTANCE hInstance)
{
	HWND hwnd;

	WNDCLASS wcex;

	memset(&wcex, 0, sizeof(WNDCLASS));
	wcex.style			= CS_HREDRAW | CS_VREDRAW;		
	wcex.lpfnWndProc	= WndProc;		
	wcex.hInstance		= hInstance;						
	wcex.hIcon			= LoadIcon(NULL, IDI_APPLICATION);; 
	wcex.hCursor		= LoadCursor(NULL, IDC_ARROW);		
	wcex.hbrBackground	= (HBRUSH) (COLOR_WINDOW+1);
	wcex.lpszMenuName	= NULL;	
	wcex.lpszClassName	= "FirstWindowClass";

	RegisterClass(&wcex);// Register the class

	dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;

	//  ghInstance	= hInstance;// Assign our global hInstance to the window's hInstance

	//Set the Client area of the window to be our resolution.
	RECT glwindow;
	glwindow.left		= 0;		
	glwindow.right		= width;	
	glwindow.top		= 0;		
	glwindow.bottom		= height;	

	AdjustWindowRect( &glwindow, dwStyle, false);

	//Create the window
	hwnd = CreateWindow("FirstWindowClass", 
		strWindowName, 
		dwStyle, 
		0, 
		0,
		glwindow.right  - glwindow.left,
		glwindow.bottom - glwindow.top, 
		NULL,
		NULL,
		hInstance,
		NULL
		);

	if(!hwnd) return NULL;// If we couldn't get a handle, return NULL

	ShowWindow(hwnd, SW_SHOWNORMAL);	
	UpdateWindow(hwnd);					
	SetFocus(hwnd);						

	return hwnd;
}

void Cleanup(HINSTANCE hInstance)
{ 
	UnregisterClass("FirstWindowClass", hInstance);// Free the window class 
	manager->release();
	delete manager;
	manager = NULL;

	PostQuitMessage (0);	      	// Post a QUIT message to the window
}

